﻿using RedisService;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace StackExchangeImpl
{
    public class Database : IDatabase
    {

        StackExchange.Redis.IDatabase database;
        public Database(StackExchange.Redis.IDatabase database)
        {
            this.database = database;
        }

        public bool Del(string key)
        {
            return database.KeyDelete(key);
        }

        public long LLen(string key)
        {
            return database.ListLength(key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public bool Lock(string key, string value, int expiry)
        {
            TimeSpan timespan = TimeSpan.FromMilliseconds(expiry);
            return database.LockTake(key, value, timespan);
        }

        public string LPop(string key)
        {
            return database.ListLeftPop(key);
        }

        public long LPush(string key, string value, KeyState keyState = KeyState.Always)
        {
            return database.ListLeftPush(key, value, (StackExchange.Redis.When)keyState);
        }

        public long LPush(string key, string[] value, KeyState keyState = KeyState.Always)
        {
            if (value != null && value.Length > 0)
            {
                var values = new StackExchange.Redis.RedisValue[value.Length];
                for (int i = 0; i < value.Length; i++)
                {
                    values[i] = value[i];
                }
               return database.ListLeftPush(key, values, (StackExchange.Redis.When)keyState);
            }
            throw new Exception("value 为空！");
        }

        public string[] LRange(string key, long start, long end)
        {
            var values = database.ListRange(key, start, end);
            if (values != null && values.Length > 0)
            {
                return values.Select(m => (String)m).ToArray();
            }
            return new string[0];
        }

        public string RPop(string key)
        {
            return database.ListRightPop(key);
        }

        public long RPush(string key, string value, KeyState keyState = KeyState.Always)
        {
            return database.ListRightPush(key, value, (StackExchange.Redis.When)keyState);
        }

        public long RPush(string key, string[] value, KeyState keyState = KeyState.Always)
        {
            if (value != null && value.Length > 0)
            {
                var values = new StackExchange.Redis.RedisValue[value.Length];
                for (int i = 0; i < value.Length; i++)
                {
                    values[i] = value[i];
                }
                return database.ListRightPush(key, values, (StackExchange.Redis.When)keyState);
            }
            throw new Exception("value 为空！");
        }

        public long StringDecr(string key, long value = 1)
        {
           return  database.StringDecrement(key, value);
        }

        public string StringGet(string key)
        {
            return database.StringGet(key);
        }

        public bool StringGetBit(string key, long offset)
        {
            return database.StringGetBit(key, offset);
        }

        public long StringIncr(string key, long value = 1)
        {
            return database.StringIncrement(key, value);
        }

        public bool StringSet(string key, string value, int? expiry = null, KeyState keyState = KeyState.Always)
        {
            TimeSpan? timespan = null; 
            if (expiry.HasValue)
            {
                timespan = TimeSpan.FromMilliseconds(expiry.Value);
            }
            return database.StringSet(key, value, timespan, (StackExchange.Redis.When)keyState);
        }

        public bool StringSetBit(string key, long offset, bool bit)
        {
            return database.StringSetBit(key, offset, bit);
        }

        public bool Unlock(string key, string value)
        {
            return database.LockRelease(key, value);
        }
    }
}
